#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vi: ts=4 expandtab
#
# Copyright (C) 2012 KT
#
# Author: Choonho Son <choonho.son@kt.com>
#

import os.path
import sys
import platform
import re
import urllib
from urllib2 import urlopen, URLError, HTTPError
from cloudutils.lib.log import CloudLog

__version__="1.0"
__all__ = ['update']

DhcpDir = {
	'CentOS' : '/var/lib/dhclient',
	'redhat' : '/var/lib/dhclient',
	}

class CloudUtils:
	"""
	This is module executor from config file
	"""
	def __init__(self):
		self.logger = CloudLog().getLogger()
		self.common = {}
		
	def install(self, target='/tmp/cloudconf.cfg'):
		(vrip,domain) = self.getVirtualRouterIP()
		self.fetchUserData(vrip, target)
		self.callModule(target)
		
	def getVirtualRouterIP(self):
		"""
		find Virtual Router IP address from dhcp info
		@return: (Virtual Router IP, Domain name) (fail: False)
		"""
		if sys.version_info < (2,6):
			(OS,ver,id) = platform.dist()
		else:
			(OS,ver,id) = platform.linux_distribution()
				
		eth = os.path.join(DhcpDir[OS], 'dhclient-eth0.leases')
		#check file exist

		self.logger.debug("Interface path:%s" % eth)
		fp = open(eth,'r')
		ip_pattern = r'(option dhcp-server-identifier) (\d+.\d+.\d+.\d+)'
		domain_pattern = r'(option domain-name) "(\S+)"'
		vrip = ''
		domain = ''
		for line in fp:
			token = re.findall(ip_pattern, line)
			token2 = re.findall(domain_pattern, line)
			if len(token) == 1:
				(k, vrip) = token[0]
			if len(token2) == 1:
				(k, domain) = token2[0]

		self.logger.info("Virtual Router IP: %s" % vrip)
		self.logger.info("Domain name : %s" % domain)
		self.common['domain'] = domain
		return (vrip, domain)
								
	def fetchUserData(self, srcIP, target):
		"""
		fetch UserData from Virtual Router
		"""
		url = "http://%s/latest/user-data" % srcIP
		urllib.urlretrieve(url, target)	

			
	def parseParam(self, msg=""):
		"""
		@param msg: parameter message string
		@return : (key, value) dictionary
		"""
		kv_pattern = r'\b(.+)\b=\b(.+)'
		params = {}
		for param in msg.split(","):
			kv = re.findall(kv_pattern, param)
			if len(kv) < 1: continue
			(k,v) = kv[0]
			self.logger.debug("key=[%s] value=[%s]" % (k,v))
			params[k] = v
		return params

	def appendCommonParams(self, msg):
		keys = self.common.keys()
		for key in keys:
			msg = msg + "," + "common.%s=%s" % (key, self.common[key])
		return msg
	
	def callModule(self, cfg):
		"""
		Call userData
		"""
		fp = open(cfg,'r')
		update_pattern = r'(cloudutils.update)\('
		method_pattern = r'(\S+)\('
		param_pattern = r'\((.+)\)'
		request = fp.read()
		fp.close()
		lines = request.split(";")
		result = ""
		output = ""
		for line in lines:
			token0 = re.findall(update_pattern, line)
			token1 = re.findall(method_pattern, line)
			token2 = re.findall(param_pattern, line)
			# parameter string
			if len(token2) == 1:
				param_string = token2[0]
			else:
				param_string = ""

			# method function
			if len(token0) == 1:
				# call updater
				module_name = "%s" % token0[0]
			elif len(token1) == 1:
				# call method
				module_name = "%s" % token1[0]
				param_string = self.appendCommonParams(param_string)
			else:
				continue
			
			self.logger.debug("Call module:%s" % module_name)
			exec("import %s as installer" % module_name)
			inst = installer
			params = self.parseParam(param_string)
			method = "inst.install"
			#method parameter is dictionary
			result = eval(method)(params)
			output = "%s==>%s" % (line, result)
		return output
	
	def removeMe(self, url='/usr/bin/post-installer.py'):
		self.logger.debug("remoteMe:%s" % url)
		if os.path.isfile(url) == True:
			result = os.remove(url)
			self.logger.debug("removed:%s" % result)

	def removeScript(self, url='/etc/rc.local',script='/usr/bin/post-installer.py'):
	        """
		Assume start script is in /etc/rc.local
		delete /usr/bin/post-installer.py
		"""
		self.logger.debug("removeScript:%s <- %s" % (url, script))
		if os.path.isfile(url) == False:
			self.logger.error("[Error] URL:%s" % url)
		fp = open(url, 'r')
		new_config = ""
		for line in fp:
			if line.find(script) >= 0:
				#delete current line
				continue
			new_config = new_config + line
		fp.close()
		self.logger.debug("Add new config\n%s" % new_config)
		fp = open(url, 'w')
		fp.write(new_config)
		fp.close()
			

if __name__ == "__main__":
	from optparse import OptionParser
	usage = "usage:%prog [options] arg"
	parser = OptionParser()
	parser.add_option("-s","--sample",dest="sample",help="Sample Config file")
	(options,args) = parser.parse_args()

	inst = CloudUtils()
	
	if options.sample:
		target = options.sample
		inst.callModule(target)
	else:
		inst.install()
